<template>
  <transition name="el-message-fade" @after-leave="handleAfterLeave">
    <div
      v-show="visible"
      :class="messageClass"
      :style="positionStyle"
      role="alert"
      @mouseenter="clearTimer"
      @mouseleave="startTimer"
    >
      <i v-if="iconClass" :class="iconClass" />
      <i v-else :class="typeClass" />
      <slot>
        <p v-if="!dangerouslyUseHTMLString" class="el-message__content">
          {{ message }}
        </p>
        <!-- eslint-disable-next-line vue/no-v-html -->
        <p v-else class="el-message__content" v-html="message" />
      </slot>
      <i
        v-if="showClose"
        class="el-message__closeBtn el-icon-close"
        @click="close"
      />
      <div v-if="badge > 1" :key="'badge' + badge" class="el-message__badge">
        {{ badge }}
      </div>
      <div
        v-if="progress && !closed"
        :key="'progress' + badge"
        class="el-message__progress"
        :style="progressStyle"
      />
    </div>
  </transition>
</template>

<script>
export default {
  data() {
    return {
      visible: false,
      badge: 1, //标记值，大于1时显示
      progress: true, //是否显示进度条
      pause: false, //是否暂停关闭
      message: '',
      duration: 3000,
      startAt: 0, //上一次开始关闭计时的时间
      remainTime: 0, //还剩多少毫秒关闭
      type: '', //默认值改为js控制
      iconClass: '',
      customClass: '',
      onClose: null,
      showClose: false,
      closed: false,
      verticalOffset: 20,
      timer: null,
      dangerouslyUseHTMLString: false,
      center: false
    }
  },

  computed: {
    messageClass() {
      return [
        'el-message',
        this.type && !this.iconClass ? `el-message--${this.type}` : '',
        this.center ? 'is-center' : '',
        this.showClose ? 'is-closable' : '',
        this.customClass
      ]
    },
    typeClass() {
      return this.type && !this.iconClass
        ? `el-message__icon el-icon-${this.type}`
        : ''
    },
    positionStyle() {
      return {
        top: `${this.verticalOffset}px`
      }
    },
    progressStyle() {
      if (!this.progress || this.closed) return 'transform: scaleX(0)'
      if (this.pause)
        return `transform: scaleX(${
          this.remainTime / this.duration
        });animation-play-state:paused`
      return `animation-duration: ${this.duration}ms;animation-play-state:running`
    }
  },

  watch: {
    closed(newVal) {
      if (newVal) this.visible = false
    }
  },

  mounted() {
    this.startTimer()
  },

  methods: {
    handleAfterLeave() {
      this.$destroy(true)
      this.$el.parentNode.removeChild(this.$el)
    },
    close() {
      this.closed = true
      typeof this.onClose === 'function' && this.onClose(this)
    },
    clearTimer(reset) {
      this.pause = true
      this.remainTime =
        reset === true
          ? this.duration
          : this.remainTime - (Date.now() - this.startAt)
      window.clearTimeout(this.timer)
    },
    startTimer() {
      if (this.duration > 0 && !this.closed) {
        this.pause = false
        this.startAt = Date.now()
        if (this.remainTime === 0) this.remainTime = this.duration
        this.timer = window.setTimeout(
          () => !this.closed && this.close(),
          this.remainTime
        )
      }
    }
  }
}
</script>
